﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using ScintillaNET;

namespace FizzDevelop
{
	class JustBASICLexer
	{
		private const int EOL = -1;
		private const int DEFAULT_STYLE = 32;		// Default SciLexer style index
		private const int LINENUMBER_STYLE = 33;	// Style for line numbers in the Margin0
		private const int KEYWORD_STYLE = 11;		// Just BASIC keywords
		private const int FUNCTION_STYLE = 12;		// Built in Just BASIC functions
		private const int SPECIALVAR_STYLE = 13;	// Special Just BASIC variables
		private const int QUOTES_STYLE = 14;		// String literals
		private const int COMMENT_STYLE = 15;		// Line comments
		private const int OPERATOR_STYLE = 16;		// Operators like =, +, etc.

		private Scintilla _Editor;
		private int _startPos;
		private int _index;
		private string _text;	// The single line of text we are styling

		public static void Init(Scintilla Editor)
		{
			Font font = new Font("Consolas", 8.25F);

			// Set up the Editor to accept custom styles. 
			Editor.Indentation.SmartIndentType = SmartIndent.None;
			Editor.ConfigurationManager.CustomLocation = String.Empty;
			Editor.ConfigurationManager.Language = String.Empty;
			Editor.Lexing.LexerName = "container";
			Editor.Lexing.Lexer = Lexer.Container;
			Editor.StyleNeeded += new EventHandler<StyleNeededEventArgs>(StyleNeeded);
			Editor.Styles[LINENUMBER_STYLE].Font = font;

			// Add Just BASIC styles to the collection
			Editor.Styles[KEYWORD_STYLE].ForeColor = Color.Blue;
			Editor.Styles[FUNCTION_STYLE].ForeColor = Color.Purple;
			Editor.Styles[SPECIALVAR_STYLE].ForeColor = Color.Purple;
			Editor.Styles[QUOTES_STYLE].ForeColor = Color.Green;
			Editor.Styles[COMMENT_STYLE].ForeColor = Color.Gray;
			Editor.Styles[KEYWORD_STYLE].Font = font;
			Editor.Styles[FUNCTION_STYLE].Font = font;
			Editor.Styles[SPECIALVAR_STYLE].Font = font;
			Editor.Styles[QUOTES_STYLE].Font = font;
			Editor.Styles[COMMENT_STYLE].Font = font;
		}

		static void StyleNeeded(object sender, StyleNeededEventArgs e)
		{
			StyleNeeded((Scintilla)sender, e.Range);
		}

		public static void StyleNeeded(Scintilla Editor, Range range)
		{
			// Create an instance of the lexer to style the line of text
			JustBASICLexer lexer = new JustBASICLexer(Editor, range.Start, range.StartingLine.Length);
			lexer.Style();
		}

		private int Read()
		{
			if (_index < _text.Length) return _text[_index];
			return EOL;
		}

		private void SetStyle(int style, int length)
		{
			if (length > 0)
			{
				((INativeScintilla)_Editor).SetStyling(length, style);
			}
		}

		public void Style()
		{
			
		}

		private void StyleUntilMatch(int style, char[] chars)
		{
			// Advance until we match a char in the array
			int startIndex = _index;
			while (_index < _text.Length && Array.IndexOf<char>(chars, _text[_index]) < 0)
				_index++;

			if (startIndex != _index)
				SetStyle(style, _index - startIndex);
		}

		private JustBASICLexer(Scintilla Editor, int startPos, int length)
        {
            this._Editor = Editor;
            this._startPos = startPos;

            // One line of _text
            this._text = Editor.GetRange(startPos, startPos + length).Text;
        }
	}
}
